/*
 *  Copyright 2010 Mahbub Mozadded Sowrov.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package com.sowrov.util.logsystem;

import java.io.File;
import java.io.IOException;

import java.net.URISyntaxException;
import java.net.URL;

import java.text.SimpleDateFormat;

import java.util.Date;

/**
 * Html formatter implementation of LogFormatter
 *
 * @author Sowrov
 * @version %I% %G%
 */
public class Html implements LogFormatter {
    private SimpleDateFormat dateFormat;

    /**
     * Default Constructor.
     */
    public Html() {
        this.dateFormat = new SimpleDateFormat("dd MMM yyyy hh:mm:ss a");
    } // end Html()

    /**
     * Construct html formatter class with a dateFormat.
     * Default date format is: "dd MMM yyyy hh:mm:ss a"
     * @param dateFormat Date format
     */
    public Html(final SimpleDateFormat dateFormat) {
        this.dateFormat = dateFormat;
    } // end Html()

    public String getCriticalFormat(
                                    final String message, final int lineNo, final String functionName,
                                    final String fileName) {
        return this.getFormat("error", message, lineNo, functionName, fileName);
    } // end getCriticalFormat()

    public String getDebugFormat(
                                 final String message, final int lineNo, final String functionName,
                                 final String fileName) {
        return this.getFormat("debug", message, lineNo, functionName, fileName);
    } // end getDebugFormat()

    public String getFatalFormat(
                                 final String message, final int lineNo, final String functionName,
                                 final String fileName) {
        return this.getFormat("fatalError", message, lineNo, functionName, fileName);
    } // end getFatalFormat()

    public String getFinalFormat() {
        String text = "<tr class='endRow'>" + " <td colspan='3'>Application Terminated at: ";
        text += this.dateFormat.format(new Date());
        text += "</td> </tr> </table> </body> </html>";

        return text;
    } // end getFinalFormat()

    public String getInfoFormat(
                                final String message, final int lineNo, final String functionName,
                                final String fileName) {
        return this.getFormat("info", message, lineNo, functionName, fileName);
    } // end getInfoFormat()

    public String getIntroFormat() {
        String jarFileName = this.getJarFileName();
        Date compileDate = this.getLastCompileDate();

        String dateTime = "Unknown";

        if (compileDate != null) {
            dateTime = this.dateFormat.format(compileDate);
        } // end if

        String intro = "<html><head><title>";
        intro += ((jarFileName.equals("") ? "" : jarFileName) + " Log ");
        intro += this.dateFormat.format(new Date());
        intro += (
                     "</title><style type=\"text/css\">" + "<!--" + "table, td" + "{" + "  border-color: #000;"
                     + "}" + "table" + "{" + "margin:auto;" + "table-layout: fixed;" + "border-width: 1px;"
                     + "border-spacing: 0;" + "border-collapse: collapse;" + "width: 90%;" + "}td{margin: 0;"
                     + "padding: 4px; border-width: 1px 1px 0 0;" + "}" + "a:link, a:visited, a:hover {"
                     + "    color:#FF3333;" + "}" + "#headRow {" + "    background-color:#000033;"
                     + "  color:#FFFFCC;" + "    font-size:large;" + "}" + ".fatalError{"
                     + " background-color:#660000;" + " color:#009900;" + "    word-wrap:break-word;" + "}"
                     + ".error{" + " background-color:#003366;" + " color:#9999CC;" + "    word-wrap:break-word;"
                     + "}" + ".warning{" + " background-color:#663366;" + " color:#FFCCCC;"
                     + "    word-wrap:break-word;" + "}" + ".info{" + " background-color:#FFFFCC;"
                     + " color:#000000;" + "    word-wrap:break-word;" + "}" + ".debug{"
                     + " background-color:#CCFFCC;" + " color:#000000;" + "    word-wrap:break-word;" + "}"
                     + ".endRow {" + " background-color:#CCCCFF;" + "}" + ".timestamp{" + "    font-size: 0.7em;"
                     + " text-align:right;" + " font-style:normal;" + "}" + "-->" + "</style>"
                     + "<script type=\"text/javascript\">" + "function OnOffSwitch(className){"
                     + "    var allClassName = ['fatalError', 'error', 'warning', 'info', 'debug'];"
                     + "    for (var it=0; it<allClassName.length; it++) {"
                     + "        if (allClassName[it]==className || className=='') {" + ""
                     + "            OnOff(allClassName[it], true);" + "        }" + " else {" + ""
                     + "                OnOff(allClassName[it], false);" + " }" + " }" + " }"
                     + "function OnOff (className, boolVal) {"
                     + " var rows = document.getElementsByClassName(className);"
                     + "    for(var i=0; i<rows.length; i++){" + "      if (boolVal == true) {"
                     + "     rows[i].style.display = '';" + "    }" + " else {"
                     + "  rows[i].style.display = 'none';" + "  }" + " }" + "}"
                     + "</script></head><body><center><h1>" + (
                                                                  jarFileName.equals("") ? "Chronicle" : jarFileName
                                                              )
                     + " Application Log</h1><sub>This Application was Compiled at: "
                 );
        intro += dateTime;
        intro += "</sub></center>";
        intro += (
                     "<div style='margin:auto; width: 90%'>"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"\")'>Show All</a>|"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"fatalError\")'>Show Fatal Only</a>|"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"error\")'>Show Error Only</a>|"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"warning\")'>Show Warning Only</a>|"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"info\")'>Show Information Only</a>|"
                     + "<a href='javascript:void(0)' onclick='OnOffSwitch(\"debug\")'>Show Debug Only</a>"
                     + "</div>" + "<table border='3'; cellpadding='5px'>" + "  <tr id='headRow'>"
                     + "    <th width='50%'>Class.Method</th>" + "    <th width='30%' >FileName:LineNo</th>"
                     + "    <th width='20%' >Timestamp</th>" + "  </tr>"
                 );

        return intro;
    } // end getIntroFormat()

    public String getWarningFormat(
                                   final String message, final int lineNo, final String functionName,
                                   final String fileName) {
        return this.getFormat("warning", message, lineNo, functionName, fileName);
    } // end getWarningFormat()

    private String getFormat(
                             final String className, final String message, final int lineNo,
                             final String functionName, final String fileName) {
        StringBuilder text = new StringBuilder("<tr class='" + className + "'>");
        text.append("<td width='50%' > ").append(functionName).append("(...)")
        .append("</td>");
        text.append("<td width='30%'>").append(fileName).append(": ").append(lineNo).append("</td>");
        text.append("<td width='20%' class='timestamp'>");
        text.append(this.dateFormat.format(new Date()));
        text.append("</td></tr> <tr class='").append(className).append("'><td colspan='3' width='100%'>");
        text.append(message).append("</td></tr>");

        return text.toString();
    } // end getFormat()

    private String getJarFileName() {
        String jarFileName = "";

        try {
            jarFileName =
                    new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getName();

            if (!jarFileName.matches(".*\\.[jJ][aA][rR]$")) {
                jarFileName = "";
            } // end if
        } // end try
        catch (final URISyntaxException ex) {
        } // end catch

        return jarFileName;
    } // end getJarFileName()

    private Date getLastCompileDate() {
        String name = this.getClass().getName();
        String path = name.replace('.', '/');

        URL fileURL = this.getClass().getResource("/" + path + ".class");

        Date compileDate = null;

        try {
            compileDate = new Date(fileURL.openConnection().getLastModified());
        } // end try
        catch (final IOException ex) {
        } // end catch

        return compileDate;
    } // end getLastCompileDate()
} // end Html
